﻿using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using Newtonsoft.Json;
using SAMPLE_A = JsonWebSignatureTests.JWSSamples_A;

namespace JsonWebSignatureTests
{
    public class JWSSamples_A
    {
        public static string JWSHead = "{\"typ\":\"JWT\",\r\n \"alg\":\"HS256\"}";
        public static string JWSHeadExptectedEncoded = "eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9";
        public static byte[] JWSHeadExptectedBytes = new byte[] { 123, 34, 116, 121, 112, 34, 58, 34, 74, 87, 84, 34, 44, 13, 10, 32, 34, 97, 108, 103, 34, 58, 34, 72, 83, 50, 53, 54, 34, 125 };
        public static string JWSPayload = "{\"iss\":\"joe\",\r\n \"exp\":1300819380,\r\n \"http://example.com/is_root\":true}";
        public static byte[] JWSPayloadExpectedBytes = new byte[] { 123, 34, 105, 115, 115, 34, 58, 34, 106, 111, 101, 34, 44, 13, 10, 32, 34, 101, 120, 112, 34, 58, 49, 51, 48, 48, 56, 49, 57, 51, 56, 48, 44, 13, 10, 32, 34, 104, 116, 116, 112, 58, 47, 47, 101, 120, 97, 109, 112, 108, 101, 46, 99, 111, 109, 47, 105, 115, 95, 114, 111, 111, 116, 34, 58, 116, 114, 117, 101, 125 };
        public static string JWSPayloadExpectedEncoded = "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ";
        public static string JWSExpectedSecuredInput = "eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ";
        public static byte[] JWSExpectedSecuredInputBytes = new byte[] { 101, 121, 74, 48, 101, 88, 65, 105, 79, 105, 74, 75, 86, 49, 81, 105, 76, 65, 48, 75, 73, 67, 74, 104, 98, 71, 99, 105, 79, 105, 74, 73, 85, 122, 73, 49, 78, 105, 74, 57, 46, 101, 121, 74, 112, 99, 51, 77, 105, 79, 105, 74, 113, 98, 50, 85, 105, 76, 65, 48, 75, 73, 67, 74, 108, 101, 72, 65, 105, 79, 106, 69, 122, 77, 68, 65, 52, 77, 84, 107, 122, 79, 68, 65, 115, 68, 81, 111, 103, 73, 109, 104, 48, 100, 72, 65, 54, 76, 121, 57, 108, 101, 71, 70, 116, 99, 71, 120, 108, 76, 109, 78, 118, 98, 83, 57, 112, 99, 49, 57, 121, 98, 50, 57, 48, 73, 106, 112, 48, 99, 110, 86, 108, 102, 81 };
        public static byte[] SigningKeyBytes = new byte[] { 3, 35, 53, 75, 43, 15, 165, 188, 131, 126, 6, 101, 119, 123, 166, 143, 90, 179, 40, 230, 240, 84, 201, 40, 169, 15, 132, 178, 210, 80, 46, 191, 211, 251, 90, 146, 210, 6, 71, 239, 150, 138, 180, 195, 119, 98, 61, 34, 61, 46, 33, 114, 5, 46, 79, 8, 192, 205, 154, 245, 103, 208, 128, 163 };
        public static byte[] SigningExpectedResultBytes = new byte[] { 116, 24, 223, 180, 151, 153, 224, 37, 79, 250, 96, 125, 216, 173, 187, 186, 22, 212, 37, 77, 105, 214, 191, 240, 91, 88, 5, 88, 83, 132, 141, 121 };
        public static string SigningExpectedResultEncoded = "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk";
        byte[] key = new byte[] { 3, 35, 53, 75, 43, 15, 165, 188, 131, 126, 6, 101, 119, 123, 166, 143, 90, 179, 40, 230, 240, 84, 201, 40, 169, 15, 132, 178, 210, 80, 46, 191, 211, 251, 90, 146, 210, 6, 71, 239, 150, 138, 180, 195, 119, 98, 61, 34, 61, 46, 33, 114, 5, 46, 79, 8, 192, 205, 154, 245, 103, 208, 128, 163 };
    }


    [TestFixture]
    public class JSWWebSignatureTests
    {
        [Test]
        public void Sample_A()
        {
            Console.WriteLine("From: http://tools.ietf.org/html/draft-ietf-jose-json-web-signature-08#appendix-A");

            // base64 head and content (payload)
            var bytes = Stub.Jwt.Utility.getBytes(SAMPLE_A.JWSHead);
            Assert.AreEqual(SAMPLE_A.JWSHeadExptectedBytes, bytes, "Head Bytes");

            var base64Head = Stub.Jwt.Utility.Base64UrlEncode(bytes);
            Assert.AreEqual(SAMPLE_A.JWSHeadExptectedEncoded, base64Head, "Head Encoded");
            Console.WriteLine("base64Head: {0}", base64Head);

            bytes = Stub.Jwt.Utility.getBytes(SAMPLE_A.JWSPayload);
            Assert.AreEqual(SAMPLE_A.JWSPayloadExpectedBytes, bytes, "Payload Bytes");

            var base64Payload = Stub.Jwt.Utility.Base64UrlEncode(bytes);
            Assert.AreEqual(SAMPLE_A.JWSPayloadExpectedEncoded, base64Payload, "Payload Encoded");
            Console.WriteLine("base64Payload: {0}", base64Payload);

            var secureInputValue = String.Format("{0}.{1}", base64Head, base64Payload);
            Assert.AreEqual(SAMPLE_A.JWSExpectedSecuredInput, secureInputValue, "Secure Input");
            Console.WriteLine("secureInputValue: {0}", secureInputValue);

            bytes = Stub.Jwt.Utility.getBytes(secureInputValue);
            Assert.AreEqual(SAMPLE_A.JWSExpectedSecuredInputBytes, bytes, "Secure Input Bytes");

            bytes = Stub.Jwt.Utility.ComputeHMACSha265(bytes, SAMPLE_A.SigningKeyBytes);
            Assert.AreEqual(SAMPLE_A.SigningExpectedResultBytes, bytes, "Signed Secure Input Bytes");

            var base64Signed = Stub.Jwt.Utility.Base64UrlEncode(bytes);
            Assert.AreEqual(SAMPLE_A.SigningExpectedResultEncoded, base64Signed);
            Console.WriteLine("base64Signed: {0}", base64Signed);
        }
    }

    [TestFixture]
    public class JSONWebTokenGeneratorClassTest
    {
        [Test]
        public void Sample_A()
        {
            Console.WriteLine("From: http://tools.ietf.org/html/draft-ietf-jose-json-web-signature-08#appendix-A");
            var jwt = new Stub.Jwt.JsonWebToken();
            var result = jwt.Generate(SAMPLE_A.JWSHead, SAMPLE_A.JWSPayload, SAMPLE_A.SigningKeyBytes);
            Assert.AreEqual(SAMPLE_A.SigningExpectedResultEncoded, result, "Signed Secure Input Bytes");
        }
    }
    
}

namespace Util
{
    [TestFixture]
    public class SigningKey
    {
        [Test]
        public void getSigningKey()
        {
            var bytes = Stub.Jwt.Utility.getBytes("n0sththfCieJOzcGsgQkcw");
            Console.Write("byte[] signingKey = new byte[] {");
            int i = bytes.Length;
            foreach (byte b in bytes)
            {
                Console.Write(b);
                if (i-- > 1)
                    Console.Write(", ");
            }
            Console.Write("};");

        }
        
    }

    [TestFixture]
    public class DecodeBase64
    {
        [Test]
        public void test1()
        {
            var s = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9";
            Console.WriteLine(Stub.Jwt.Utility.Base64UrlDecode(s));
            s = "eyJpc3MiOiIwMDI5MTUxMTQ5NDk0MzQ0Nzg5NSIsImF1ZCI6Ikdvb2dsZSIsInR5cCI6Imdvb2dsZS9wYXltZW50cy9pbmFwcC9pdGVtL3YxIiwiaWF0IjoiMTM3MjQ0NDA4OCIsImV4cCI6IjEzNzI1MzA0ODgiLCJyZXF1ZXN0Ijp7ImN1cnJlbmN5Q29kZSI6IlVTRCIsInByaWNlIjoiMy4wMCIsIm5hbWUiOiJHb2xkIFN0YXIiLCJzZWxsZXJEYXRhIjoic29tZSBvcGFxdWUgZGF0YSIsImRlc2NyaXB0aW9uIjoiQSBzaGluaW5nIGJhZGdlIG9mIGRpc3RpbmN0aW9uIn19";
            Console.WriteLine(Stub.Jwt.Utility.Base64UrlDecode(s));
        }

        [TestCase(@"eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJHb29nbGUiLCJyZXF1ZXN0Ijp7Im5hbWUiOiJQaWVjZSBvZiBDYWtlIiwiZGVzY3JpcHRpb24iOiJBIGRlbGljaW91cyBwaWVjZSBvZiB2aXJ0dWFsIGNha2UiLCJwcmljZSI6IjEuMDAiLCJjdXJyZW5jeUNvZGUiOiJVU0QiLCJzZWxsZXJEYXRhIjoiWW91ciBEYXRhIEhlcmUifSwicmVzcG9uc2UiOnsib3JkZXJJZCI6IjEyNTQyNDU3ODE3NDAyMDIzNjkwLmMzYzY1NTc4LTdhYmYtNDg1ZC1hNWMyLWQzNDQ1ZWQxNDFlNiJ9LCJ0eXAiOiJnb29nbGUvcGF5bWVudHMvaW5hcHAvaXRlbS92MS9wb3N0YmFjay9idXkiLCJhdWQiOiIxNTYzODUzODY5ODM2NjkwMzIxMiIsImlhdCI6MTM3MjYxMzc4MCwiZXhwIjoxMzcyNjEzODAwfQ.zDlSn5pGddetah15wgYQUQuJIo8CLmGGzfacxzAy0f4")]
        public void DecodePostBack(String PostBack)
        {
            Stub.Jwt.JsonWebToken jwt = new Stub.Jwt.JsonWebToken(PostBack);
            Assert.True(jwt.Valid("RxMr0dZSP9WAfKC5vJ_n3w"));
        }
    }
}

namespace GoogleWalletSandbox.Kstubs
{
    [TestFixture]
    public class WalletDigitalGoods
    {
        public static string JWSHead = "{\"typ\":\"JWT\",\"alg\":\"HS256\"}";
        public static string SellerID = "00291511494943447895";
        public static string Secret = "yLgaDShnxiisPlFYiW0CTA";
        public static string PayLoad = 
            "{" +
            "\"iss\":\"" + SellerID + "\"," +
            "\"aud\":\"Google\"," +
            "\"typ\":\"google/payments/inapp/item/v1\"," +
            "\"iat\":\"1372444088\"," +
            "\"exp\":\"1372530488\"," +
            "\"request\":{" +
            "\"currencyCode\":\"USD\"," +
            "\"price\":\"3.00\"," +
            "\"name\":\"Gold Star\"," +
            "\"sellerData\":\"some opaque data\"," +
            "\"description\":\"A shining badge of distinction\"" +
            "}}";

        [Test]
        public void ThePayload()
        {
            Console.WriteLine(PayLoad);
        }
        [Test]
        public void GetJWT()
        {

            var jwt = new Stub.Jwt.JsonWebToken();
            string j = jwt.Generate(JWSHead, PayLoad, Stub.Jwt.Utility.getBytes(Secret));
            Console.WriteLine(j);
            
        }
    }

}
namespace GoogleWalletSandbox.MSO
{
    [TestFixture]
    public class WalletDigitalGoods
    {
        public static string JWSHead = "{\"typ\":\"JWT\",\"alg\":\"HS256\"}";
        public static string SellerID = "15638538698366903212";
        public static string Secret = "n0sththfCieJOzcGsgQkcw";
        public static string PayLoad =
            "{" +
            "\"iss\":\"" + SellerID + "\"," +
            "\"aud\":\"Google\"," +
            "\"typ\":\"google/payments/inapp/item/v1\"," +
            "\"iat\":\"1372444088\"," +
            "\"exp\":\"1372530488\"," +
            "\"request\":{" +
            "\"currencyCode\":\"USD\"," +
            "\"price\":\"3.00\"," +
            "\"name\":\"Gold Star\"," +
            "\"sellerData\":\"some opaque data\"," +
            "\"description\":\"A shining badge of distinction\"" +
            "}}";

        [Test]
        public void ThePayload()
        {
            Console.WriteLine(PayLoad);
        }
        [Test]
        public void GetJWT()
        {
            var jwt = new Stub.Jwt.JsonWebToken();
            string j = jwt.Generate(JWSHead, PayLoad, Stub.Jwt.Utility.getBytes(Secret));
            Console.WriteLine(j);

        }
    }

}
namespace GoogleTutorialTests
{
    [TestFixture]
    public class OAuth2Sample
    {
        public static string JWSHead = "{\"typ\":\"JWT\",\"alg\":\"RS256\"}";
        public static string PayLoad = "{" +
                                       "\"iss\":\"761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com\"," +
                                       "\"scope\":\"https://www.googleapis.com/auth/prediction\"," +
                                        "\"aud\":\"https://accounts.google.com/o/oauth2/token\"," +
                                        "\"exp\":1328554385," +
                                        "\"iat\":1328550785}";
        [Test]
        public void Sample1()
        {
            Console.WriteLine("From:  https://developers.google.com/accounts/docs/OAuth2ServiceAccount");

            var jwt = new Stub.Jwt.JsonWebToken();

            var signkey = Stub.Jwt.Utility.getBytes("Zing");
            Console.WriteLine(jwt.Generate(JWSHead, PayLoad, signkey));
        }
    }

    // from https://checkout.google.com/inapp/merchant/demo.html?mbi=12542457817402023690&mbr=seller
    public class GoogleSample1
    {
        public static string JWSHead = "{\"typ\":\"JWT\",\"alg\":\"RS256\"}";
        public static string JWTExpected = "eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiIxNTYzODUzODY5ODM2N" +
         "jkwMzIxMiIsImF1ZCI6Ikdvb2dsZSIsInR5cCI6Imdvb2dsZS9" +
         "wYXltZW50cy9pbmFwcC9pdGVtL3YxIiwiaWF0IjoxMzcyNjI2O" +
         "TgwLCJleHAiOjEzNzI3MTMzODAsInJlcXVlc3QiOnsiY3VycmV" +
         "uY3lDb2RlIjoiVVNEIiwicHJpY2UiOiIzLjAwIiwibmFtZSI6I" +
         "kdvbGQgU3RhciIsInNlbGxlckRhdGEiOiJzb21lIG9wYXF1ZSB" +
         "kYXRhIiwiZGVzY3JpcHRpb24iOiJBIHNoaW5pbmcgYmFkZ2Ugb" +
         "2YgZGlzdGluY3Rpb24ifX0.HRbnFyEC042rLSQqfEPIFSji48T" +
         "unB_Ra9yAMcs1JDQ";

        public static string JWTJsonExpected = "{" +
  "\"iss\":\"15638538698366903212\"," +
  "\"aud\":\"Google\"," +
  "\"typ\":\"google/payments/inapp/item/v1\"," +
  "\"iat\":1372626980," +
  "\"exp\":1372713380," +
  "\"request\":{" +
    "\"currencyCode\":\"USD\"," +
    "\"price\":\"3.00\"," +
    "\"name\":\"Gold Star\"," +
    "\"sellerData\":\"some opaque data\"," +
    "\"description\":\"A shining badge of distinction\"" +
  "}}";

        [Test]
        public void GenJWT()
        {
            var jwt = new Stub.Jwt.JsonWebToken();

            var sig = Stub.Jwt.Utility.getBytes("RxMr0dZSP9WAfKC5vJ_n3w");
            var j = jwt.Generate(JWSHead, JWTJsonExpected, sig);
            Console.WriteLine(j);
            Assert.AreEqual(JWTExpected, j);
        }

        [Test]
        public void GenJWT_TestValid()
        {
            var jwt = new Stub.Jwt.JsonWebToken();

            var sig = Stub.Jwt.Utility.getBytes("RxMr0dZSP9WAfKC5vJ_n3w");
            var j = jwt.Generate(JWSHead, JWTJsonExpected, sig);
            Console.WriteLine(j);
            Assert.IsTrue(jwt.Valid("RxMr0dZSP9WAfKC5vJ_n3w"));
        }
    }

    public class TutorialTests
    {
        [Test]
        public void testTutorial1Sample()
        {
            Console.WriteLine("See: https://developers.google.com/commerce/wallet/digital/docs/tutorial#1");
            StringWriter writer = new StringWriter();
            JsonTextWriter jwriter = new JsonTextWriter(writer);

            jwriter.WriteStartObject();

            // iat
            jwriter.WritePropertyName("iat");
            jwriter.WriteValue("1372434190");
            // exp
            jwriter.WritePropertyName("exp");
            jwriter.WriteValue("1372520590");
            // request (obj)
            jwriter.WritePropertyName("request");
            jwriter.WriteStartObject();
            //  name
            jwriter.WritePropertyName("name");
            jwriter.WriteValue("Gold Star");

            //  description
            jwriter.WritePropertyName("description");
            jwriter.WriteValue("A shining badge of distinction");
            //  price
            jwriter.WritePropertyName("price");
            jwriter.WriteValue("3.00");

            //  currencyCode
            jwriter.WritePropertyName("currencyCode");
            jwriter.WriteValue("USD");

            //  sellerData
            jwriter.WritePropertyName("sellerData");
            jwriter.WriteValue("some opaque data");

            jwriter.WriteEnd();
            jwriter.WriteEnd();

            var payload = writer.ToString();

            Assert.AreEqual(GoogleTutorialTests.GoogleSample1.JWTJsonExpected, payload);
            Console.WriteLine(payload);

            var jwt = new Stub.Jwt.JsonWebToken();
            var j = jwt.Generate(GoogleTutorialTests.GoogleSample1.JWSHead, payload, "");
            Assert.AreEqual(GoogleTutorialTests.GoogleSample1.JWTExpected, j);
        }

    }
}
